#ifndef TIMER_H
#define TIMER_H

#include <iostream>
#include <string>
#ifdef linux
#include <sys/time.h>
#elif defined(_WIN32)
#include <windows.h>
#else
#error Not support this system
#endif

/**
  计时器类，计算从调用start开始到调用printSeconds所花销的时间
  */
class Timer
{
public:

    Timer() {
        _name = "Time elapsed:";
        restart();
    }

    Timer(const std::string &name) {
        _name = name+":";
        restart();
    }

    /**
     * 启动计时
     */
    inline void  restart() {
#ifdef linux
		gettimeofday(&_start_time, nullptr);
#elif defined(_WIN32)
        QueryPerformanceFrequency(&_freq);
        QueryPerformanceCounter(&_start_time);
#endif
    }

    /**
     * 结束计时
     * @return 返回ms数
     */
	inline double elapsed()
    {
#ifdef linux
		gettimeofday(&_end_time, nullptr);
		double  elapsedTime = double(_end_time.tv_sec - _start_time.tv_sec)*1000.0f +
			(_end_time.tv_usec - _start_time.tv_usec) / 1000.0f;
#elif defined(_WIN32)
        QueryPerformanceCounter(&_end_time);
		double  elapsedTime = (_end_time.QuadPart - _start_time.QuadPart)*1000.0/_freq.QuadPart;
#endif
        return  elapsedTime;
    }

    /**
     * 打印时间
     * @param unit_ms true是ms，false是s
     * @param tip 输出提示
     * @param restart_after_call 输出之后是否重启计时器，true重启，false不重启
     * @param exit_after_call 输出之后是否退出程序，true退出，false不退出
     */
    void log(const std::string &tip = "", bool unit_ms = true,
             bool restart_after_call = false, bool exit_after_call = false
    ){
        if(unit_ms){
            if(tip.length()>0)
                printf("%s: %lfms\n",tip.c_str(),elapsed());
            else
                printf("%s: %lfms\n",_name.c_str(),elapsed());
        }else{
            if(tip.length()>0)
                printf("%s: %lfs\n",tip.c_str(),elapsed()/1000.0);
            else
                printf("%s: %lfs\n",_name.c_str(),elapsed()/1000.0);
        }

        if(restart_after_call)
            restart();

        if(exit_after_call)
            exit(5);
    }


private:
#ifdef linux
	struct timeval _start_time;
	struct timeval _end_time;
#elif defined(_WIN32)
    LARGE_INTEGER _freq;
    LARGE_INTEGER _start_time;
    LARGE_INTEGER _end_time;
#endif
    std::string _name;
}; // Timer

#endif